#!/usr/bin/env python

#############################################################################
# dcontrol.py: Module for simplifying control of Deluge.
#############################################################################
# Copyright (C) 2012
#
# Authors: Dan Larkin <danielhlarkin@gmail.com>
#          Yonatan Naamad <cached@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#############################################################################

import urllib, os, sys, re

# Import the client module
from deluge.ui.client import client
# Import the reactor module from Twisted - this is for our mainloop
from twisted.internet import reactor
# Set up the logger to print out errors
from deluge.log import setupLogger

from twisted.internet.threads import blockingCallFromThread as block

import base64
import logging
import threading

import network
import torrent

OPTIONS = {'auto_managed':False}

def _shift_str(s,amt):
    return "".join(map(lambda x: chr(ord(x)+amt),s))
    
def _on_connect_success(result):
    logging.info("Connection to deluge daemon successful.")
    
def _on_connect_failure(result):
    logging.error("Unable to connect to deluge daemon. Error: '%s'." % result)
    
def init(torrents_dir, files_dir):
    '''Establishes connection to Deluge. 
       Must be run before any of these controls can be used.'''
    setupLogger() #for debugging
    
    DControl.conn = client.connect()
    DControl.conn.addCallback(_on_connect_success)
    DControl.conn.addErrback(_on_connect_failure)
    
    DControl.torrents_dir = torrents_dir
    DControl.files_dir = files_dir
    
    reactor.run(installSignalHandlers=0)
    
def disconnect():
    '''Close connection to Deluge.'''
    client.disconnect()
    reactor.stop()
    
def add_torrent(torrent, up_throttle=None, down_throttle=None):
    '''Joins the swarm associated with a given .torrent file'''
    torrent_file = torrent.get_file()
    t_hash = torrent.get_hex()
    
    t_id = client.core.add_torrent_file(torrent_file, 
                                        base64.encodestring(open(torrent_file).read()),
                                        {'download_location': os.path.join(DControl.files_dir,t_hash),
                                         'auto_managed':False})
    if up_throttle:
        set_up_throttle(torrent.get_bin(), up_throttle)
        
    if down_throttle:
        set_down_throttle(torrent.get_bin(), down_throttle)

def remove_torrent(torrent):
    '''Leaves the torrent's swarm, but does not delete the associated files.'''
    return block(reactor, client.core.remove_torrent, torrent.get_hex(), False)

del_torrent = remove_torrent
        
def set_up_throttle(torrent, new_up):
    '''Throttle upload rate of torrent to new_up KB/s'''
    client.core.set_torrent_max_upload_speed(torrent.get_hex(), new_up)
    
def set_down_throttle(torrent, new_down):
    '''Throttle download rate of torrent to new_up KB/s'''
    client.core.set_torrent_max_download_speed(torrent.get_hex(), new_down)
    
def get_torrents_info(torrents=None, keys=[]):
    '''Get information specified in keys about list of torrents.
       If torrents is None, instead returns info about *all* torrents.'''
       
    if torrents == None: #get all active torrents
        d = {}
        s = block(reactor, client.core.get_torrents_status, {}, keys)
        for i in s:
            d[torrent.get_instance(i,torrent._HEX)] = s[i]
        return d
    else:
        res = {}
        for i in torrents:
            res[i] = block(reactor, client.core.get_torrent_status, i.get_hex(),keys)
        return res
        
def get_upload_rate(torrent):
    return get_torrents_info([torrent],['upload_payload_rate'])[torrent]['upload_payload_rate'] // 1024

def get_download_rate(torrent):
    return get_torrents_info([torrent],['download_payload_rate'])[torrent]['download_payload_rate'] // 1024

def get_active_torrents():
    '''Gets the identifiers (sha1 hashes) of active torrents.'''
    return block(reactor, client.core.get_session_state)
    
class DControl(object):
    conn = None
    torrents_dir = None
    files_dir = None
